use serde::{Deserialize, Serialize};
use tauri_plugin_opener::OpenerExt;
use std::fs;
use std::io::Read;
use std::path::Path;


#[derive(Debug, Serialize, Deserialize)]
pub struct FileItem {
    pub name: String,
    pub path: String,
    pub is_dir: bool,
    pub size: u64,
    pub timestamp: String,
}

#[tauri::command]
// 将当前目录下的文件和目录列出
pub fn list_directory(path: String) 
-> Result<Vec<FileItem>, String> {
    let dir_path = Path::new(&path);
    if !dir_path.exists() {
        return Err(format!("❌Path does not exist."));
    }
    if !dir_path.is_dir() {
        return Err(format!("❌Path is not a directory."));
    }

    let entries = match fs::read_dir(path) {
        Ok(entries) => entries,
        Err(e) => return Err(format!("❌Failed to read directory: {}", e)),
    };

    let mut files = Vec::new();

    for entry in entries {
        if let Ok(entry) = entry {
            let file_path = entry.path();
            let metadata = match fs::metadata(&file_path) {
                Ok(meta) => meta,
                Err(_) => continue, // Skip files we can't get metadata for
            };

            let name = match file_path.file_name() {
                Some(name) => match name.to_str() {
                    Some(name_str) => name_str.to_string(),
                    None => continue, // Skip files with invalid UTF-8 names
                },
                None => continue, // Skip files without names
            };

            files.push(FileItem {
                name,
                path: file_path.to_string_lossy().to_string(),
                is_dir: metadata.is_dir(),
                size: if metadata.is_file() {
                    metadata.len()
                } else {
                    0
                },
                timestamp: { "" }.to_string(),
            });
        }
    }
    // Sort directories first, then files
    files.sort_by(|a, b| match (a.is_dir, b.is_dir) {
        (true, false) => std::cmp::Ordering::Less,
        (false, true) => std::cmp::Ordering::Greater,
        _ => a.name.to_lowercase().cmp(&b.name.to_lowercase()),
    });

    Ok(files)
}

#[tauri::command]
pub async fn open_file(app_handle: tauri::AppHandle, path: String) -> Result<(), String> {
    app_handle
        .opener()
        .open_path(path, None::<&str>)
        .map_err(|e| format!("❌Failed to open file: {}", e))
}

// 读取文件内容
#[tauri::command]
pub fn read_file_content(path: String) -> Result<String, String> {
    let mut file = fs::File::open(&path).map_err(|e| format!("❌Failed to open file: {}", e))?;
    let mut content = String::new();
    file.read_to_string(&mut content)
        .map_err(|e| format!("❌Failed to read file: {}", e))?;

    Ok(content)
}

// 删除文件或目录
#[tauri::command]
pub fn delete_file(path: String) -> Result<(), String> {
    let path_obj = Path::new(&path);
    // 检查路径是否存在
    if !path_obj.exists() {
        return Err(format!("❌Path does not exist: {}", path));
    }
    // 根据是文件还是目录选择不同的删除方法
    if path_obj.is_file() {
        fs::remove_file(path_obj).map_err(|e| format!("❌Failed to delete file: {}", e))
    } else if path_obj.is_dir() {
        fs::remove_dir_all(path_obj).map_err(|e| format!("❌Failed to delete directory: {}", e))
    } else {
        Err(format!(
            "❌Path is neither a file nor a directory: {}",
            path
        ))
    }
}

#[tauri::command]
//判断传入的字符串是否是路径
pub async fn get_path_metadata(path: String) -> Result<serde_json::Value, String> {
    let metadata = std::fs::metadata(path).map_err(|e| format!("获取元数据失败: {}", e))?;
    Ok(serde_json::json!({
        "is_dir": metadata.is_dir(),
        "exists": true
    })) 
} 

#[tauri::command]
pub fn read_file_bytes(path: String) -> Result<Vec<u8>, String> {
    fs::read(&path).map_err(|e| format!("Failed to read file: {}", e))
}

fn get_file_name(file_path: &Path) -> Result<String, String> {
    file_path.file_name()
        .and_then(|n| n.to_str())
        .map(|s| s.to_string())
        .ok_or_else(|| "❌Invalid file path".to_string())
}
// 写入二进制文件内容 
#[tauri::command]
pub fn write_file_bytes(path: String, contents: Vec<u8>) -> Result<(), String> {
    let file_path = Path::new(&path);
    let result = fs::write(file_path, &contents)
    .map_err(|e| format!("❌Failed to write file: {}", e))?;
    let file_name = get_file_name(file_path)?;
    println!("File name: {}", file_name);
    Ok(result) 
}
 
#[tauri::command]
pub fn write_text_file(path: String, contents: Vec<u8>) -> Result<(), String> {
    let file_path = Path::new(&path);
    let content_str = String::from_utf8(contents)
        .map_err(|e| format!("❌Filed to convert to string: {}", e))?;
    let result = fs::write(file_path, content_str)
        .map_err(|e| format!("❌Failed to write file: {}", e))?;
    let file_name = get_file_name(file_path)?;
    println!("File name: {}", file_name);
    Ok(result)
}

